# @FileName  : tool.py
# @Time      : 2022/4/10 0010  11:44
# @Author    : LuZhaoHui
# @Software  : PyCharm

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PIL import Image
from configparser import ConfigParser
import os, csv, codecs, xlsxwriter, openpyxl, time, datetime, shutil

# IMG_EXT = (".jpg")
# XLS_EXT = (".xls", ".xlsx")
DEFAULT_DPI = (300.0, 300.0)
ROTATE_TYPE = {'1': 90, '2': 180, '3': 270}

# 图片信息：段标识(1-0xff)+段类型(1-IMG_XXXX)+段长度(2)+段内容(n)
# 段类型
IMG_MARK = 0xff  # 段标识
IMG_SOI = 0xd8  # 文件头
IMG_APP0 = 0xe0  # 定义交换格式和图像识别信息
IMG_APP1 = 0xe1  #
IMG_APPF = 0xef  #
IMG_DQT = 0xdb  # 定义量化表
IMG_DRI = 0xdd  # 定义重新开始间隔
IMG_SOF0 = 0xc0  # 帧开始
IMG_SOF1 = 0xc1
IMG_DHT = 0xc4  # 定义HUFFMAN表
IMG_SOS = 0xda  # 扫描行开始
IMG_EOI = 0xd9  # 文件尾
IMG_COM = 0xfe  # 注释


def nowDateStr():
    return datetime.datetime.now().strftime('%Y-%m-%d')


def nowTimeStr():
    return datetime.datetime.now().strftime('%H:%M:%S')


def copyFile(src, des):
    dir = os.path.dirname(des)
    if not os.path.exists(dir):
        os.makedirs(dir)
    return shutil.copy(src, des)


def saveLog(msg, path, log=''):
    if not os.path.exists(path):
        os.makedirs(path)
    if len(log) == 0:
        file = path + '/log.txt'
    else:
        file = path + '/' + log
    with open(file, 'a', encoding='utf-8') as f:
        str = nowDateStr() + ' ' + nowTimeStr() + ' ' + msg + '\n'
        f.write(str)
    return str


def setComboBoxHeight(combo, h):
    combo.setStyleSheet("QAbstractItemView::item{height: %dpx;}" % (h))
    combo.setView(QListView())


def pathJoin(path1, path2):
    return os.path.join(path1, path2).replace('\\', '/')


def getImg0File(file):
    size = [0, 0]
    unit = 0
    density = [0, 0]
    dot = [0, 0]
    with open(file, 'rb') as f:
        l = 64 * 1024
        data = f.read(l)
        i = 0
        while i < l:
            # i += 1
            if data[i] == IMG_MARK:
                i += 1
                continue
            elif data[i] == IMG_APP0:
                # 图像识别信息
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                j = i + 2
                j += 5
                j += 2
                unit = data[j]
                j += 1
                ch = data[j]
                cl = data[j + 1]
                density[0] = ch * 256 + cl
                j += 2
                ch = data[j]
                cl = data[j + 1]
                density[1] = ch * 256 + cl
                j += 2
                dot[0] = data[j]
                j += 1
                dot[1] = data[j]
                i += len
                continue
            elif data[i] == IMG_COM or (data[i] >= IMG_APP1 and data[i] <= IMG_APPF):
                # 图像识别信息
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                i += len
                continue
            elif data[i] == IMG_SOI:
                i += 1
                continue
            elif data[i] == IMG_DQT:
                i += 1
                ch = data[i]
                cl = data[i + 1]
                len = ch * 256 + cl
                i += len
                continue
            elif data[i] == IMG_SOF0:
                # 图像基本信息:段标识(1,FF),段类型(1,C0),段长度(2,8＋组件数量×3)
                i += 3
                # 样本精度(1,8),图片高度(2),图片宽度(2)
                i += 1
                ch = data[i]
                i += 1
                cl = data[i]
                size[1] = ch * 256 + cl
                i += 1
                ch = data[i]
                i += 1
                cl = data[i]
                size[0] = ch * 256 + cl
                # 组件数量(1,1＝灰度图，3＝YCbCr / YIQ,4＝CMYK),（以下每个组件占用３字节）
                break
            else:
                break
    return size + density


def getImgFile(file, isSet):
    try:
        image = Image.open(file)
    except Exception:
        return (0, 0, 0.0, 0.0, 'RGB')
    if 'dpi' in image.info:
        if image.info['dpi'][0] != 300 or image.info['dpi'][1] != 300:
            if isSet:
                image.save(file, dpi=(300, 300))
            else:
                return image.size + (image.info['dpi'][0], image.info['dpi'][1]) + tuple([image.mode])
        return image.size + (300, 300) + tuple([image.mode])
    else:
        if isSet:
            image.save(file, dpi=(300, 300))
            return image.size + (300, 300) + tuple([image.mode])
        else:
            return image.size + (0.0, 0.0) + tuple([image.mode])


def resizeImage(nameA, nameB):
    img = getImgFile(nameA, False)
    image = Image.open(nameB)
    new_image = image.resize((img[0], img[1]), Image.ANTIALIAS)
    new_image.save(nameB, dpi=(300, 300))


def rotateImage(name, set):
    image = Image.open(name)
    if set == '1':
        image = image.transpose(Image.ROTATE_90)
    elif set == '2':
        image = image.transpose(Image.ROTATE_180)
    elif set == '3':
        image = image.transpose(Image.ROTATE_270)
    image.save(name, dpi=DEFAULT_DPI)


def showLabelImage(area, label, name, self):
    img = QImage()
    img.load(name)
    if self:
        w = area.width()
        h = area.height()
        new_img = img.scaled(w, h, Qt.KeepAspectRatio)
        label.setPixmap(QPixmap.fromImage(new_img))
    else:
        label.setPixmap(QPixmap.fromImage(img))


def writeXlsx(name, data):
    try:
        write = xlsxwriter.Workbook(name)
        sheet = write.add_worksheet()
        for i, cols in enumerate(data):
            for j, d in enumerate(cols):
                if isinstance(d, list):
                    l = len(d)
                    for k, dd in enumerate(d):
                        sheet.write(i, j * l + k, dd)
                else:
                    sheet.write(i, j, d)
        write.close()
    except Exception as err:
        print(err)


def writeCsv(name, data):
    try:
        file_csv = codecs.open(name, 'w+', 'utf-8')
        writer = csv.writer(file_csv, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        for d in data:
            writer.writerow(d)
    except Exception as err:
        print(err)


def readXlsx(name):
    data = []
    if os.path.exists(name):
        read = openpyxl.load_workbook(name)
        sheets = read.get_sheet_names()
        sheet = read.get_sheet_by_name(sheets[0])
        rows = sheet.rows
        for row in rows:
            line = [col.value for col in row]
            data.append(line)
    return data


def readCsv(name, type=[]):
    data = []
    if os.path.exists(name):
        if os.path.exists(name):
            with open(name, encoding='utf-8') as csvfile:
                csv_reader = csv.reader(csvfile)
                cmd = 'data.append(row)'
                if len(type) > 0:
                    cmd = 'data.append(['
                    for i, t in enumerate(type):
                        if t == 'int':
                            cmd += 'int(row[%d]),' % (i)
                            continue
                        if t == 'float':
                            cmd += 'float(row[%d]),' % (i)
                            continue
                        cmd += 'row[%d],' % (i)
                    cmd = cmd[:-1] + '])'
                for row in csv_reader:
                    exec(cmd)
                    # data.append(row)
    return data


class MyParser(ConfigParser):
    "Inherit from built-in class: ConfigParser"

    def optionxform(self, optionstr):
        "Rewrite without lower()"
        return optionstr


class hdConf():
    def __init__(self, file):
        self.initVar()
        self.config = MyParser()
        self.name = file
        self.readConf()

    def initVar(self):
        # 设计配置
        self.varConf = {'Title': '海淀数据核查',
                        'ConfPath': '',
                        'ImagePath': '',
                        'BackupPath': '',
                        'UnitPos': 0,
                        'TypePos': 0,
                        'WindowMax': 0}
        self.varUnitList = []
        self.varTypeList = ['全部']

    def getConfig(self, section, key):
        return self.config.get(section, key)

    def readConf(self):
        self.config.read(self.name, 'utf-8')
        # [CONF]
        for k in self.varConf:
            str = self.getConfig('CONF', k)
            if isinstance(self.varConf[k], int):
                self.varConf[k] = int(str)
            else:
                self.varConf[k] = str
        for k in range(10):
            name = 'UnitName%d' % (k + 1)
            try:
                str = self.getConfig('UNIT', name)
                fl = str.split(',')
                if len(fl) > 0:
                    self.varUnitList.extend(fl)
            except Exception as e:
                print(e)
        str = self.getConfig('UNIT', 'TypeName')
        self.varTypeList.extend(str.split(','))

    def writeConf(self, key, value):
        self.config.set('CONF', key, str(value))
        with open(self.name, 'w', encoding='utf-8') as f:
            self.config.write(f)


# 扫描线程
class ScanSrcFileListThread(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, srcList, csvName):
        super().__init__()
        self.srcList = srcList
        self.csvName = csvName

    def run(self):
        if len(self.srcList) == 0:
            self.update_item.emit(['读取配置...'])
            self.srcList = readCsv(self.csvName)
        self.update_item.emit(['配置[%d]' % (len(self.srcList))])
        for i, f in enumerate(self.srcList):
            flist = [i]
            if len(f) == 1:
                flist.extend(['', '', f[0], '0', '0', '0', '0', '0', '[]', '[]'])
            else:
                flist.extend(f)
            self.update_item.emit(flist)
        self.update_item.emit([])


# 处理线程
class ProcFileListThread(QThread):
    update_item = pyqtSignal(list)

    def __init__(self, procDict):
        super().__init__()
        self.dict = procDict

    def run(self):
        for k, v in self.dict.items():
            if v == '0000':
                continue
            time.sleep(0.5)
            self.update_item.emit([k])
        self.update_item.emit([])
